Implement lots of value setters for GdkGC, based on a heavily modified
authorMichael Natterer <mitch@imendio.com>
Thu, 21 Sep 2006 17:05:33 +0000 (17:05 +0000)
committerMichael Natterer <mitch@src.gnome.org>
Thu, 21 Sep 2006 17:05:33 +0000 (17:05 +0000)
2006-09-21  Michael Natterer  <mitch@imendio.com>

       Implement lots of value setters for GdkGC, based on a heavily
       modified patch from Thomas Broyer (bug #328853):

* gdk/quartz/gdkcolor-quartz.c: removed functions which set colors
on the CGContext. Instead, added gdk_quartz_get_rgba_from_pixel()
which simply returns RGBA values from a GdkColor's pixel value.
See gdk_quartz_update_context_from_gc() below.

* gdk/quartz/gdkprivate-quartz.h (struct GdkGCQuartz): added lots
of members for the newly suppored GC values. Added enum
GdkQuartzContextValuesMask which is used for setting up the
CGContext for filling and/or stroking.

* gdk/quartz/gdkgc-quartz.c (gdk_quartz_gc_get_values)
(gdk_quartz_gc_set_values)
(_gdk_windowing_gc_copy): support a lot more GC values.

(gdk_quartz_update_context_from_gc): added
GdkQuartzContextValuesMask parameter and set filling/stroking
parameters accordingly. This function also gained full control
over the FG and BG colors (they can't be set separately any more).

The stipple mask part of the patch doesn't work but seems to take
the right approach and doesn't make things worse, so I applied it.

Did *not* apply the clipping part of the patch since I don't
understand it (I don't understand the version in CVS either, but
it at least works :-)

* gdk/quartz/gdkdrawable-quartz.c: pass the right masks to
gdk_quartz_update_context_from_gc() and removed separate color
setting calls. Some minor fixes.

* gdk/quartz/gdkwindow-quartz.c
(gdk_window_impl_quartz_begin_paint_region): set the CGContext's
fill color manually. We don't have/need a GC here.

ChangeLog
gdk/quartz/gdkcolor-quartz.c
gdk/quartz/gdkdrawable-quartz.c
gdk/quartz/gdkgc-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkwindow-quartz.c

index e9f896e223efc41d60540f14be6b44e2a58b9946..77c6a51bccad8424bda612ac83f6625e7c16c5ce 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2006-09-21  Michael Natterer  <mitch@imendio.com>
+
+       Implement lots of value setters for GdkGC, based on a heavily
+       modified patch from Thomas Broyer (bug #328853):
+
+       * gdk/quartz/gdkcolor-quartz.c: removed functions which set colors
+       on the CGContext. Instead, added gdk_quartz_get_rgba_from_pixel()
+       which simply returns RGBA values from a GdkColor's pixel value.
+       See gdk_quartz_update_context_from_gc() below.
+
+       * gdk/quartz/gdkprivate-quartz.h (struct GdkGCQuartz): added lots
+       of members for the newly suppored GC values. Added enum
+       GdkQuartzContextValuesMask which is used for setting up the
+       CGContext for filling and/or stroking.
+
+       * gdk/quartz/gdkgc-quartz.c (gdk_quartz_gc_get_values)
+       (gdk_quartz_gc_set_values)
+       (_gdk_windowing_gc_copy): support a lot more GC values.
+
+       (gdk_quartz_update_context_from_gc): added
+       GdkQuartzContextValuesMask parameter and set filling/stroking
+       parameters accordingly. This function also gained full control
+       over the FG and BG colors (they can't be set separately any more).
+
+       The stipple mask part of the patch doesn't work but seems to take
+       the right approach and doesn't make things worse, so i applied it.
+
+       Did *not* apply the clipping part of the patch since I don't
+       understand it (I don't understand the version in CVS either, but
+       it at least works :-)
+
+       * gdk/quartz/gdkdrawable-quartz.c: pass the right masks to
+       gdk_quartz_update_context_from_gc() and removed separate color
+       setting calls. Some minor fixes.
+
+       * gdk/quartz/gdkwindow-quartz.c
+       (gdk_window_impl_quartz_begin_paint_region): set the CGContext's
+       fill color manually. We don't have/need a GC here.
+
 2006-09-21  Michael Natterer  <mitch@imendio.com>
 
        * gdk/quartz/gdkwindow-quartz.c
index 07e726c4d08bf912a5b4b30e5cbe00d38db321be..40d40b208b405a6a835b55cb8a14605e0b3a5bc8 100644 (file)
@@ -170,37 +170,21 @@ gdk_colormap_get_screen (GdkColormap *cmap)
 }
 
 void
-gdk_quartz_set_context_fill_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel)
+gdk_quartz_get_rgba_from_pixel (GdkColormap *colormap,
+                               guint32      pixel,
+                               float       *red,
+                               float       *green,
+                               float       *blue,
+                               float       *alpha)
 {
-  float red, green, blue, alpha;
-
-  red = (pixel >> 16 & 0xff) / 255.0;
-  green = (pixel >> 8 & 0xff) / 255.0;
-  blue = (pixel & 0xff) / 255.0;
-
-  if (colormap && gdk_colormap_get_visual (colormap)->depth == 32)
-    alpha = (pixel >> 24 & 0xff) / 255.0;
-  else
-    alpha = 1.0;
-
-  CGContextSetRGBFillColor (context, red, green, blue, alpha);
-}
-
-void
-gdk_quartz_set_context_stroke_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel)
-{
-  float red, green, blue, alpha;
-
-  red = (pixel >> 16 & 0xff) / 255.0;
-  green = (pixel >> 8 & 0xff) / 255.0;
-  blue = (pixel & 0xff) / 255.0;
-
+  *red   = (pixel >> 16 & 0xff) / 255.0;
+  *green = (pixel >> 8  & 0xff) / 255.0;
+  *blue  = (pixel       & 0xff) / 255.0;
   if (colormap && gdk_colormap_get_visual (colormap)->depth == 32)
-    alpha = (pixel >> 24 & 0xff) / 255.0;
+    *alpha = (pixel >> 24 & 0xff) / 255.0;
   else
-    alpha = 1.0;
-
-  CGContextSetRGBStrokeColor (context, red, green, blue, 1.0);  
+    *alpha = 1.0;
 }
 
 gboolean
index 3142fa4c3529d34b7a77381d8ea7b96965ff839d..030f68362e186e33edab456bb8e3eb10c7190ec5 100644 (file)
@@ -128,22 +128,21 @@ gdk_quartz_draw_rectangle (GdkDrawable *drawable,
   if (!context)
     return;
 
-  gdk_quartz_update_context_from_gc (context, gc);
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    filled ?
+                                    GDK_QUARTZ_CONTEXT_FILL :
+                                    GDK_QUARTZ_CONTEXT_STROKE);
 
   if (filled)
     {
       CGRect rect = CGRectMake (x, y, width, height);
 
-      gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                   _gdk_gc_get_fg_pixel (gc));
       CGContextFillRect (context, rect);
     }
   else
     {
       CGRect rect = CGRectMake (x + 0.5, y + 0.5, width, height);
 
-      gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                     _gdk_gc_get_fg_pixel (gc));
       CGContextStrokeRect (context, rect);
     }
 
@@ -167,7 +166,10 @@ gdk_quartz_draw_arc (GdkDrawable *drawable,
   if (!context)
     return;
 
-  gdk_quartz_update_context_from_gc (context, gc);
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    filled ?
+                                    GDK_QUARTZ_CONTEXT_FILL :
+                                    GDK_QUARTZ_CONTEXT_STROKE);
 
   CGContextSaveGState (context);
 
@@ -176,9 +178,6 @@ gdk_quartz_draw_arc (GdkDrawable *drawable,
 
   if (filled)
     {
-      gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                    _gdk_gc_get_fg_pixel (gc));
-
       CGContextTranslateCTM (context,
                              x + width / 2.0,
                              y + height / 2.0);
@@ -193,9 +192,6 @@ gdk_quartz_draw_arc (GdkDrawable *drawable,
     }
   else
     {
-      gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                     _gdk_gc_get_fg_pixel (gc));
-
       CGContextTranslateCTM (context,
                              x + width / 2.0 + 0.5,
                              y + height / 2.0 + 0.5);
@@ -225,13 +221,13 @@ gdk_quartz_draw_polygon (GdkDrawable *drawable,
   if (!context)
     return;
 
-  gdk_quartz_update_context_from_gc (context, gc);
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    filled ?
+                                    GDK_QUARTZ_CONTEXT_FILL :
+                                    GDK_QUARTZ_CONTEXT_STROKE);
 
   if (filled)
     {
-      gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                   _gdk_gc_get_fg_pixel (gc));
-
       CGContextMoveToPoint (context, points[0].x, points[0].y);
       for (i = 1; i < npoints; i++)
        CGContextAddLineToPoint (context, points[i].x, points[i].y);
@@ -241,9 +237,6 @@ gdk_quartz_draw_polygon (GdkDrawable *drawable,
     }
   else
     {
-      gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                     _gdk_gc_get_fg_pixel (gc));
-
       CGContextMoveToPoint (context, points[0].x + 0.5, points[0].y + 0.5);
       for (i = 1; i < npoints; i++)
        CGContextAddLineToPoint (context, points[i].x + 0.5, points[i].y + 0.5);
@@ -318,9 +311,8 @@ gdk_quartz_draw_drawable (GdkDrawable *drawable,
       if (!context)
        return;
 
-      gdk_quartz_update_context_from_gc (context, gc);
-
-      CGContextSetBlendMode (context, kCGBlendModeNormal);
+      gdk_quartz_update_context_from_gc (context, gc,
+                                        GDK_QUARTZ_CONTEXT_STROKE);
 
       CGContextClipToRect (context, CGRectMake (xdest, ydest, width, height));
       CGContextTranslateCTM (context, xdest - xsrc, ydest - ysrc);
@@ -349,9 +341,9 @@ gdk_quartz_draw_points (GdkDrawable *drawable,
   if (!context)
     return;
 
-  gdk_quartz_update_context_from_gc (context, gc);
-  gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                               _gdk_gc_get_fg_pixel (gc));
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    GDK_QUARTZ_CONTEXT_STROKE |
+                                    GDK_QUARTZ_CONTEXT_FILL);
 
   /* Just draw 1x1 rectangles */
   for (i = 0; i < npoints; i++) 
@@ -375,9 +367,8 @@ gdk_quartz_draw_segments (GdkDrawable    *drawable,
   if (!context)
     return;
 
-  gdk_quartz_update_context_from_gc (context, gc);
-  gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                 _gdk_gc_get_fg_pixel (gc));
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    GDK_QUARTZ_CONTEXT_STROKE);
 
   for (i = 0; i < nsegs; i++)
     {
@@ -402,16 +393,14 @@ gdk_quartz_draw_lines (GdkDrawable *drawable,
   if (!context)
     return;
 
-  gdk_quartz_update_context_from_gc (context, gc);
-  gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable),
-                                                 _gdk_gc_get_fg_pixel (gc));
-  
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    GDK_QUARTZ_CONTEXT_STROKE);
+
+  CGContextMoveToPoint (context, points[0].x + 0.5, points[0].y + 0.5);
+
   for (i = 1; i < npoints; i++)
-    {
-      CGContextMoveToPoint (context, points[i - 1].x + 0.5, points[i - 1].y + 0.5);
-      CGContextAddLineToPoint (context, points[i].x + 0.5, points[i].y + 0.5);
-    }
-  
+    CGContextAddLineToPoint (context, points[i].x + 0.5, points[i].y + 0.5);
+
   CGContextStrokePath (context);
 
   gdk_quartz_drawable_release_context (drawable, context);
@@ -462,9 +451,8 @@ gdk_quartz_draw_pixbuf (GdkDrawable     *drawable,
   CGDataProviderRelease (data_provider);
   CGColorSpaceRelease (colorspace);
 
-  gdk_quartz_update_context_from_gc (context, gc);
-
-  CGContextSetBlendMode (context, kCGBlendModeNormal);
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    GDK_QUARTZ_CONTEXT_STROKE);
 
   CGContextClipToRect (context, CGRectMake (dest_x, dest_y, width, height));
   CGContextTranslateCTM (context, dest_x - src_x, dest_y - src_y + pixbuf_height);
@@ -509,9 +497,8 @@ gdk_quartz_draw_image (GdkDrawable     *drawable,
   CGDataProviderRelease (data_provider);
   CGColorSpaceRelease (colorspace);
 
-  gdk_quartz_update_context_from_gc (context, gc);
-
-  CGContextSetBlendMode (context, kCGBlendModeNormal);
+  gdk_quartz_update_context_from_gc (context, gc,
+                                    GDK_QUARTZ_CONTEXT_STROKE);
 
   CGContextClipToRect (context, CGRectMake (xdest, ydest, width, height));
   CGContextTranslateCTM (context, xdest - xsrc, ydest - ysrc + image->height);
index d18721568babc9b5aa69703e6ee79c340cef72ae..b1e140de6e24ae8ec1d9b54dc54fe2e0693eca4e 100644 (file)
@@ -33,14 +33,12 @@ gdk_quartz_gc_get_values (GdkGC       *gc,
 
   private = GDK_GC_QUARTZ (gc);
 
-  memset (values, 0, sizeof (GdkGCValues));
-  
-  /* FIXME: Fill in more value as/if they are added. */
-
   values->foreground.pixel = _gdk_gc_get_fg_pixel (gc);
   values->background.pixel = _gdk_gc_get_bg_pixel (gc);
 
-  values->function = GDK_COPY;
+  values->font = private->font;
+
+  values->function = private->function;
 
   values->fill = _gdk_gc_get_fill (gc);
   values->tile = _gdk_gc_get_tile (gc);
@@ -53,6 +51,13 @@ gdk_quartz_gc_get_values (GdkGC       *gc,
   values->ts_y_origin = gc->ts_y_origin;
   values->clip_x_origin = gc->clip_x_origin;
   values->clip_y_origin = gc->clip_y_origin;
+
+  values->graphics_exposures = private->graphics_exposures;
+
+  values->line_width = private->line_width;
+  values->line_style = private->line_style;
+  values->cap_style = private->cap_style;
+  values->join_style = private->join_style;
 }
 
 static void
@@ -62,7 +67,19 @@ gdk_quartz_gc_set_values (GdkGC           *gc,
 {
   GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
 
-  private->values_mask |= mask;
+  if (mask & GDK_GC_FONT)
+    {
+      /* FIXME: implement font */
+    }
+
+  if (mask & GDK_GC_FUNCTION)
+    private->function = values->function;
+
+  if (mask & GDK_GC_SUBWINDOW)
+    private->subwindow_mode = values->subwindow_mode;
+
+  if (mask & GDK_GC_EXPOSURES)
+    private->graphics_exposures = values->graphics_exposures;
 
   if (mask & GDK_GC_CLIP_MASK)
     {
@@ -76,15 +93,35 @@ gdk_quartz_gc_set_values (GdkGC           *gc,
       else
        private->clip_mask = NULL;
     }
+
+  if (mask & GDK_GC_LINE_WIDTH)
+    private->line_width = values->line_width;
+
+  if (mask & GDK_GC_LINE_STYLE)
+    private->line_style = values->line_style;
+
+  if (mask & GDK_GC_CAP_STYLE)
+    private->line_style = values->line_style;
+
+  if (mask & GDK_GC_JOIN_STYLE)
+    private->join_style = values->join_style;
 }
 
 static void
 gdk_quartz_gc_set_dashes (GdkGC *gc,
-                        gint   dash_offset,
-                        gint8  dash_list[],
-                        gint   n)
+                         gint   dash_offset,
+                         gint8  dash_list[],
+                         gint   n)
 {
-  /* FIXME: Implement */
+  GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
+  gint i;
+
+  private->dash_count = n;
+  g_free (private->dash_lengths);
+  private->dash_lengths = g_new (gfloat, n);
+  for (i = 0; i < n; i++)
+    private->dash_lengths[i] = (gfloat) dash_list[i];
+  private->dash_phase = (gfloat) dash_offset;
 }
 
 static void
@@ -186,20 +223,40 @@ _gdk_windowing_gc_copy (GdkGC *dst_gc,
   GdkGCQuartz *dst_quartz_gc = GDK_GC_QUARTZ (dst_gc);
   GdkGCQuartz *src_quartz_gc = GDK_GC_QUARTZ (src_gc);
 
-  dst_quartz_gc->values_mask = src_quartz_gc->values_mask;
-  
+  if (dst_quartz_gc->font)
+    gdk_font_unref (dst_quartz_gc->font);
+  dst_quartz_gc->font = src_quartz_gc->font;
+  if (dst_quartz_gc->font)
+    gdk_font_ref (dst_quartz_gc->font);
+
+  dst_quartz_gc->function = src_quartz_gc->function;
+  dst_quartz_gc->subwindow_mode = src_quartz_gc->subwindow_mode;
+  dst_quartz_gc->graphics_exposures = src_quartz_gc->graphics_exposures;
+
   dst_quartz_gc->have_clip_region = src_quartz_gc->have_clip_region;
   dst_quartz_gc->have_clip_mask = src_quartz_gc->have_clip_mask;
 
-  if (dst_quartz_gc->values_mask & GDK_GC_CLIP_MASK && dst_quartz_gc->clip_mask)
+  if (dst_quartz_gc->clip_mask)
     {
       CGImageRelease (dst_quartz_gc->clip_mask);
       dst_quartz_gc->clip_mask = NULL;
     }
   
-  if (src_quartz_gc->values_mask & GDK_GC_CLIP_MASK && src_quartz_gc->clip_mask)
+  if (src_quartz_gc->clip_mask)
     dst_quartz_gc->clip_mask =
       CGImageCreateCopy (GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (src_quartz_gc->clip_mask)->impl)->image);
+
+  dst_quartz_gc->line_width = src_quartz_gc->line_width;
+  dst_quartz_gc->line_style = src_quartz_gc->line_style;
+  dst_quartz_gc->cap_style = src_quartz_gc->cap_style;
+  dst_quartz_gc->join_style = src_quartz_gc->join_style;
+
+  if (dst_quartz_gc->dash_lengths)
+    g_free (dst_quartz_gc->dash_lengths);
+  dst_quartz_gc->dash_lengths = g_memdup (src_quartz_gc->dash_lengths,
+                                         sizeof (float) * src_quartz_gc->dash_count);
+  dst_quartz_gc->dash_count = src_quartz_gc->dash_count;
+  dst_quartz_gc->dash_phase = src_quartz_gc->dash_phase;
 }
 
 GdkScreen *  
@@ -208,12 +265,80 @@ gdk_gc_get_screen (GdkGC *gc)
   return _gdk_screen;
 }
 
+static void
+gdk_quartz_draw_tiled_pattern (void         *info,
+                              CGContextRef  context)
+{
+  GdkGC      *gc = GDK_GC (info);
+  CGImageRef  pattern_image;
+
+  pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl)->image;
+
+  CGContextDrawImage (context, CGRectMake (0, 0,
+                                          CGImageGetWidth (pattern_image),
+                                          CGImageGetHeight (pattern_image)),
+                     pattern_image);
+}
+
+static void
+gdk_quartz_draw_stippled_pattern (void         *info,
+                                 CGContextRef  context)
+{
+  GdkGC      *gc = GDK_GC (info);
+  CGImageRef  pattern_image;
+  CGRect      rect;
+  gfloat      r, g, b, a;
+
+  pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+  rect = CGRectMake (0, 0,
+                    CGImageGetWidth (pattern_image),
+                    CGImageGetHeight (pattern_image));
+
+  CGContextClipToMask (context, rect, pattern_image);
+  gdk_quartz_get_rgba_from_pixel (gc->colormap, _gdk_gc_get_fg_pixel (gc),
+                                 &r, &g, &b, &a);
+  CGContextSetRGBFillColor (context, r, g, b, a);
+  CGContextFillRect (context, rect);
+}
+
+static void
+gdk_quartz_draw_opaque_stippled_pattern (void         *info,
+                                        CGContextRef  context)
+{
+  GdkGC      *gc = GDK_GC (info);
+  CGImageRef  pattern_image;
+  CGRect      rect;
+  gfloat      r, g, b, a;
+
+  pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+  rect = CGRectMake (0, 0,
+                    CGImageGetWidth (pattern_image),
+                    CGImageGetHeight (pattern_image));
+
+  gdk_quartz_get_rgba_from_pixel (gc->colormap, _gdk_gc_get_bg_pixel (gc),
+                                 &r, &g, &b, &a);
+  CGContextSetRGBFillColor (context, r, g, b, a);
+  CGContextFillRect (context, rect);
+
+  CGContextClipToMask (context, rect, pattern_image);
+  gdk_quartz_get_rgba_from_pixel (gc->colormap, _gdk_gc_get_fg_pixel (gc),
+                                 &r, &g, &b, &a);
+  CGContextSetRGBFillColor (context, r, g, b, a);
+  CGContextFillRect (context, rect);
+}
+
 void
-gdk_quartz_update_context_from_gc (CGContextRef context, GdkGC *gc)
+gdk_quartz_update_context_from_gc (CGContextRef                context,
+                                  GdkGC                      *gc,
+                                  GdkQuartzContextValuesMask  mask)
 {
   GdkGCQuartz *private;
+  guint32      fg_pixel;
+  guint32      bg_pixel;
+
+  g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
 
-  if (gc == NULL)
+  if (!gc)
     return;
 
   private = GDK_GC_QUARTZ (gc);
@@ -258,4 +383,189 @@ gdk_quartz_update_context_from_gc (CGContextRef context, GdkGC *gc)
                                       CGImageGetHeight (private->clip_mask)),
                           private->clip_mask);
     }
+
+  fg_pixel = _gdk_gc_get_fg_pixel (gc);
+  bg_pixel = _gdk_gc_get_bg_pixel (gc);
+
+  {
+    CGBlendMode blend_mode = kCGBlendModeNormal;
+
+    switch (private->function)
+      {
+      case GDK_COPY:
+       blend_mode = kCGBlendModeNormal;
+       break;
+
+      case GDK_INVERT:
+       blend_mode = kCGBlendModeExclusion;
+       fg_pixel = 0xffffffff;
+       bg_pixel = 0xffffffff;
+       break;
+
+      case GDK_XOR:
+       blend_mode = kCGBlendModeExclusion;
+       break;
+
+      case GDK_CLEAR:
+      case GDK_AND:
+      case GDK_AND_REVERSE:
+      case GDK_AND_INVERT:
+      case GDK_NOOP:
+      case GDK_OR:
+      case GDK_EQUIV:
+      case GDK_OR_REVERSE:
+      case GDK_COPY_INVERT:
+      case GDK_OR_INVERT:
+      case GDK_NAND:
+      case GDK_NOR:
+      case GDK_SET:
+       blend_mode = kCGBlendModeNormal; /* FIXME */
+       break;
+      }
+
+    CGContextSetBlendMode (context, blend_mode);
+  }
+
+  /* FIXME: implement subwindow mode */
+
+  /* FIXME: implement graphics exposures */
+
+  if (mask & GDK_QUARTZ_CONTEXT_STROKE)
+    {
+      CGLineCap  line_cap  = kCGLineCapButt;
+      CGLineJoin line_join = kCGLineJoinMiter;
+      gfloat     r, g, b, a;
+
+      gdk_quartz_get_rgba_from_pixel (gc->colormap, fg_pixel,
+                                     &r, &g, &b, &a);
+      CGContextSetRGBStrokeColor (context, r, g, b, a);
+
+      CGContextSetLineWidth (context, MAX (G_MINFLOAT, private->line_width));
+
+      switch (private->line_style)
+       {
+       case GDK_LINE_SOLID:
+         CGContextSetLineDash (context, 0.0, NULL, 0);
+         break;
+
+       case GDK_LINE_DOUBLE_DASH:
+         /* FIXME: Implement; for now, fall back to GDK_LINE_ON_OFF_DASH */
+
+       case GDK_LINE_ON_OFF_DASH:
+         CGContextSetLineDash (context, private->dash_phase,
+                               private->dash_lengths, private->dash_count);
+         break;
+       }
+
+      switch (private->cap_style)
+        {
+       case GDK_CAP_NOT_LAST:
+         /* FIXME: Implement; for now, fall back to GDK_CAP_BUTT */
+       case GDK_CAP_BUTT:
+         line_cap = kCGLineCapButt;
+         break;
+       case GDK_CAP_ROUND:
+         line_cap = kCGLineCapRound;
+         break;
+       case GDK_CAP_PROJECTING:
+         line_cap = kCGLineCapSquare;
+         break;
+       }
+
+      CGContextSetLineCap (context, line_cap);
+
+      switch (private->join_style)
+        {
+       case GDK_JOIN_MITER:
+         line_join = kCGLineJoinMiter;
+         break;
+       case GDK_JOIN_ROUND:
+         line_join = kCGLineJoinRound;
+         break;
+       case GDK_JOIN_BEVEL:
+         line_join = kCGLineJoinBevel;
+         break;
+       }
+
+      CGContextSetLineJoin (context, line_join);
+    }
+
+  if (mask & GDK_QUARTZ_CONTEXT_FILL)
+    {
+      GdkFill         fill = _gdk_gc_get_fill (gc);
+      CGColorSpaceRef baseSpace;
+      CGColorSpaceRef patternSpace;
+      gfloat          alpha     = 1.0;
+      gfloat          colors[4] = { 0.0, 0.0, 0.0, 0.0 };
+      gfloat          r, g, b, a;
+
+      if (fill == GDK_SOLID)
+       {
+         gdk_quartz_get_rgba_from_pixel (gc->colormap, fg_pixel,
+                                         &r, &g, &b, &a);
+         CGContextSetRGBFillColor (context, r, g, b, a);
+       }
+      else
+       {
+         if (!private->ts_pattern)
+           {
+             CGImageRef pattern_image = NULL;
+             gfloat     width, height;
+             gboolean   is_colored = FALSE;
+             CGPatternCallbacks callbacks =  { 0, NULL, NULL };
+
+             switch (fill)
+               {
+               case GDK_TILED:
+                 pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl)->image;
+                 is_colored = TRUE;
+                 callbacks.drawPattern = gdk_quartz_draw_tiled_pattern;
+                 break;
+               case GDK_STIPPLED:
+                 pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+                 is_colored = FALSE;
+                 callbacks.drawPattern = gdk_quartz_draw_stippled_pattern;
+                 break;
+               case GDK_OPAQUE_STIPPLED:
+                 pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+                 is_colored = TRUE;
+                 callbacks.drawPattern = gdk_quartz_draw_opaque_stippled_pattern;
+                 break;
+               default:
+                 break;
+               }
+
+             width  = CGImageGetWidth (pattern_image);
+             height = CGImageGetHeight (pattern_image);
+
+             private->ts_pattern = CGPatternCreate (private,
+                                                    CGRectMake (0, 0, width, height),
+                                                    CGAffineTransformIdentity,
+                                                    width, height,
+                                                    kCGPatternTilingConstantSpacing,
+                                                    is_colored,
+                                                    &callbacks);
+           }
+
+         baseSpace = (fill == GDK_STIPPLED) ? CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB) : NULL;
+         patternSpace = CGColorSpaceCreatePattern (baseSpace);
+
+         CGContextSetFillColorSpace (context, patternSpace);
+         CGColorSpaceRelease (patternSpace);
+         CGColorSpaceRelease (baseSpace);
+
+         if (fill == GDK_STIPPLED)
+           gdk_quartz_get_rgba_from_pixel (gc->colormap, fg_pixel,
+                                            &colors[0], &colors[1],
+                                           &colors[2], &colors[3]);
+         CGContextSetFillPattern (context, private->ts_pattern,
+                                  (fill == GDK_STIPPLED) ? colors : &alpha);
+       }
+    }
+
+  if (mask & GDK_QUARTZ_CONTEXT_TEXT)
+    {
+      /* FIXME: implement text */
+    }
 }
index a1772ca71ba55dc30a118be034b78f332a4f4cdf..70a33031743cf7970fea3130b9def7a68d13a4f7 100644 (file)
@@ -50,13 +50,27 @@ typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
 
 struct _GdkGCQuartz
 {
-  GdkGC parent_instance;
+  GdkGC             parent_instance;
 
-  GdkGCValuesMask values_mask;
+  GdkFont          *font;
+  GdkFunction       function;
+  GdkSubwindowMode  subwindow_mode;
+  gboolean          graphics_exposures;
 
-  gboolean have_clip_region;
-  gboolean have_clip_mask;
-  CGImageRef clip_mask;
+  gboolean          have_clip_region;
+  gboolean          have_clip_mask;
+  CGImageRef        clip_mask;
+
+  gint              line_width;
+  GdkLineStyle      line_style;
+  GdkCapStyle       cap_style;
+  GdkJoinStyle      join_style;
+
+  gfloat           *dash_lengths;
+  gint              dash_count;
+  gfloat            dash_phase;
+
+  CGPatternRef      ts_pattern;
 };
 
 struct _GdkGCQuartzClass
@@ -98,10 +112,22 @@ void _gdk_events_init           (void);
 void _gdk_visual_init           (void);
 void _gdk_input_init            (void);
 
-void gdk_quartz_set_context_fill_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel);
-void gdk_quartz_set_context_stroke_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel);
-
-void gdk_quartz_update_context_from_gc (CGContextRef context, GdkGC *gc);
+typedef enum {
+  GDK_QUARTZ_CONTEXT_STROKE = 1 << 0,
+  GDK_QUARTZ_CONTEXT_FILL   = 1 << 1,
+  GDK_QUARTZ_CONTEXT_TEXT   = 1 << 2
+} GdkQuartzContextValuesMask;
+
+void gdk_quartz_get_rgba_from_pixel    (GdkColormap *colormap,
+                                       guint32      pixel,
+                                       gfloat      *red,
+                                       gfloat      *green,
+                                       gfloat      *blue,
+                                       gfloat      *alpha);
+
+void gdk_quartz_update_context_from_gc (CGContextRef                context,
+                                       GdkGC                      *gc,
+                                       GdkQuartzContextValuesMask  mask);
 
 gint        _gdk_quartz_get_inverted_screen_y      (gint y);
 
index e01e0046d689e3ada81adaedf64cd8a2afdd57fd..23ad06361cf1cc2a3239dea7e5c6647773ebdecb 100644 (file)
@@ -171,11 +171,16 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
     
       for (i = 0; i < n_rects; i++) 
         {
-          gdk_quartz_set_context_fill_color_from_pixel 
-           (context, gdk_drawable_get_colormap (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper),
-            GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper)->bg_color.pixel);
-         
-          CGContextFillRect (context, CGRectMake (rects[i].x, rects[i].y, rects[i].width, rects[i].height));
+         gfloat r, g, b, a;
+
+         gdk_quartz_get_rgba_from_pixel (gdk_drawable_get_colormap (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper),
+                                         GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper)->bg_color.pixel,
+                                         &r, &g, &b, &a);
+
+         CGContextSetRGBFillColor (context, r, g, b, a);
+          CGContextFillRect (context,
+                            CGRectMake (rects[i].x, rects[i].y,
+                                        rects[i].width, rects[i].height));
         }
       
       gdk_quartz_drawable_release_context (GDK_DRAWABLE (impl), context);